package
{
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.text.TextField;

	public class Snooker extends Sprite
	{
		private var mycue:cue;
		private var balls:Array;
		private var holes:Array;
		private var mainball:ball;
		private var ballnum:Number=7;
		private var friction:Number=0.99;
		private var bounce:Number=-1;
		private var shotpower:Number;
		private var top:Number=50;
		private var left:Number=50;
		private var right:Number=stage.stageWidth - 50;
		private var bottom:Number=stage.stageHeight - 50;
		private var stopball:uint=0;
		private var shottext:TextField
		private var shotnum:uint;

		public function Snooker()
		{
			init();
		}

		private function init():void
		{
			stage.align=StageAlign.TOP_LEFT
			stage.scaleMode=StageScaleMode.NO_SCALE

			shotnum=0
			shottext=new TextField()
			addChild(shottext)
			shottext.text="shot:  " + shotnum + "  123"
			shottext.x=100
			shottext.y=top - 20
			shottext.width=right
			shottext.textColor=0xcc00dd
			shottext.thickness=2
			graphics.lineStyle(2);
			graphics.drawRect(left, top, right - left, bottom - top);
			var ballsize:uint=15;
			balls=new Array()
			holes=new Array()
			var holepos:Array=new Array([left + ballsize, top + ballsize], [left + ballsize, bottom - ballsize], [right - ballsize, top + ballsize], [right - ballsize, bottom - ballsize])
			for (var j:uint=0; j < 4; j++)
			{
				var hole:ball=new ball(20, 0xffffff);
				hole.graphics.lineStyle(1);
				hole.graphics.drawCircle(0, 0, 20);
				hole.graphics.drawCircle(0, 0, ballsize + 10);
				hole.x=holepos[j][0];
				hole.y=holepos[j][1];
				holes.push(hole)
				addChild(hole);
			}

			for (var i:uint=0; i < ballnum; i++)
			{

				var myball:ball=new ball(ballsize, Math.random() * 0xffffff);
				myball.mass=1;
				//myball.vx=Math.random()*10-5
				//myball.vy=Math.random()*10-5
				balls.push(myball);
				addChild(myball);
				myball.x=400 + Math.floor(i / 4) * 50
				myball.y=200 + i % 4 * 40
			}
			mainball=new ball(ballsize, 0xcccccc);
			mainball.x=left + 100
			mainball.mass=2
			mainball.y=stage.stageHeight / 2;
			addChild(mainball);
			balls.push(mainball);
			mycue=new cue(ballsize);
			addChild(mycue);
			addEventListener(Event.ENTER_FRAME, onenterframe);
			addEventListener(Event.ENTER_FRAME, checkcuerotaion);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onmmousedown);
		}

		private function checkcuerotaion(E:Event):void
		{
			var angle:Number=Math.atan2(mouseY - mainball.y, mouseX - mainball.x) * 180 / Math.PI;
			mycue.x=mainball.x;
			mycue.y=mainball.y;
			mycue.rotation=angle;
		}

		private function onmmousedown(E:MouseEvent):void
		{
			mycue.gatherpower();
			stage.addEventListener(MouseEvent.MOUSE_UP, onmouseup);
		}

		private function onmouseup(E:MouseEvent):void
		{
			shotnum+=1
			shottext.text="shot:  " + shotnum + " 123"
			mycue.shot();
			shotpower=mycue.shotpower;
			var angle:Number=(mycue.rotation + 180) / 180 * Math.PI;
			var vx:Number=Math.cos(angle) * shotpower / 15;
			var vy:Number=Math.sin(angle) * shotpower / 15;
			mainball.vx=vx;
			mainball.vy=vy;
			//mycue.visible=false;
			stage.removeEventListener(MouseEvent.MOUSE_UP, onmouseup);
			removeEventListener(Event.ENTER_FRAME, checkcuerotaion);
			stage.removeEventListener(MouseEvent.MOUSE_DOWN, onmmousedown);
		}

		private function onenterframe(E:Event):void
		{
			stopball=0;
			for (var i:uint=0; i < balls.length; i++)
			{
				var myball:ball=balls[i];
				checkwall(myball);
				myball.x+=myball.vx;
				myball.y+=myball.vy;
				myball.vx*=friction;
				myball.vy*=friction;

				if (Math.abs(myball.vx) < 0.05 && Math.abs(myball.vy) < 0.05)
				{

					stopball+=1;

				}
			}
			if (stopball == balls.length)
			{
				addEventListener(Event.ENTER_FRAME, checkcuerotaion);
				stage.addEventListener(MouseEvent.MOUSE_DOWN, onmmousedown);
				mycue.visible=true;
			}
			for (i=0; i < balls.length; i++)
			{
				var balla:ball=balls[i];
				for (var j:Number=i + 1; j < balls.length; j++)
				{
					if (balls[j] != balla)
					{
						var ballb:ball=balls[j];
						checkcollision(balla, ballb);
					}
				}
			}
		}

		private function checkwall(myball:ball):void
		{
			for (var i:uint=0; i < 4; i++)
			{
				var hole:*=holes[i]
				var holedis:Number=Math.sqrt((hole.x - myball.x) * (hole.x - myball.x) + (hole.y - myball.y) * (hole.y - myball.y));
				if (holedis < hole.radius)
				{
					//removeChild(myball);
					myball.visible=false
					myball.x=-1000
					//balls.splice(i,1);
					if (myball == mainball)
					{
						myball.x=left + 100
						mainball.y=stage.stageHeight / 2;
						myball.visible=true
						mainball.vx=mainball.vy=0
					}
				}
			}
			if (myball.x - myball.radius < left)
			{
				myball.x=left + myball.radius;
				myball.vx*=bounce;
			}
			else if (myball.y - myball.radius < top)
			{
				myball.y=top + myball.radius;
				myball.vy*=bounce;
			}
			else if (myball.x + myball.radius > right)
			{
				myball.x=right - myball.radius;
				myball.vx*=bounce;
			}
			else if (myball.y + myball.radius > bottom)
			{
				myball.y=bottom - myball.radius;
				myball.vy*=bounce;
			}
		}

		private function checkcollision(ball0:ball, ball1:ball):void
		{

			var dx:Number=ball1.x - ball0.x;
			var dy:Number=ball1.y - ball0.y;
			var dis:Number=Math.sqrt(dx * dx + dy * dy);
			if (dis < ball0.radius + ball1.radius)
			{
				var angle:Number=Math.atan2(dy, dx);
				//旋转ball0的位置
				var re0:Point=new Point(0, 0);
				//旋转ball1的位置
				var re1:Point=rotate(dx, dy, angle, true);
				//旋转ball0的速度
				var rev0:Point=rotate(ball0.vx, ball0.vy, angle, true);
				//旋转ball1的速度
				var rev1:Point=rotate(ball1.vx, ball1.vy, angle, true);
				var vxtotal:Number=rev0.x - rev1.x;
				rev0.x=((ball0.mass - ball1.mass) * rev0.x + 2 * ball1.mass * rev1.x) / (ball0.mass + ball1.mass);
				rev1.x=vxtotal + rev0.x;
				var absv:Number=Math.abs(rev0.x) + Math.abs(rev1.x); //速度的绝对值之和
				var overlap:Number=(ball0.radius + ball1.radius) - Math.abs(re0.x - re1.x);
				re0.x+=rev0.x / absv * overlap;
				re1.x+=rev1.x / absv * overlap;
				//将位置旋转回去
				var p0final:Point=rotate(re0.x, re0.y, angle, false);
				var p1final:Point=rotate(re1.x, re1.y, angle, false);
				//还原速度
				var v0final:Point=rotate(rev0.x, rev0.y, angle, false);
				var v1final:Point=rotate(rev1.x, rev1.y, angle, false);
				ball0.vx=v0final.x;
				ball0.vy=v0final.y;
				ball1.vx=v1final.x;
				ball1.vy=v1final.y;
			}
		}

		private function rotate(px:Number, py:Number, angle:Number, reverse:Boolean):Point
		{
			var cos:Number=Math.cos(angle);
			var sin:Number=Math.sin(angle);
			var point:Point=new Point();
			if (reverse)
			{
				point.x=cos * px + sin * py;
				point.y=cos * py - sin * px;
			}
			else
			{
				point.x=cos * px - sin * py;
				point.y=cos * py + sin * px;
			}
			return point;
		}
	}
}
